/*
 * Inventory.java
 * Team qq 2011
 */
package com.google.code.timetrail.backend;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * This class provides an object to simulate and inventory 
 * and does things like adding and subtracting items from
 * the inventory 
 * @author Anurrag
 * @version 1.01
 * Removed magic numbers and made it so that inventories get 
 * instantiated as empty and are filled in based
 * on what Persons do
 *
 *
 */
public class Inventory implements Serializable {
    /*
     * TODO consider how oxen type items (engines I guess) would work, IE 
     * would they be in the ship or would they be in the inventory
     */
    
    
	/** Inventory's SerialVersion ID, to be changed when the object is changed **/
	private static final long serialVersionUID = 20L;

	/**
     * engines - instance of the engine held within the inventory
     */
    /**
     * fCapacitors - instance of the FluxCapacitors held within the inventory.
     */
    /**
     * hullParts - instance of HullPart to be held within the inventory.
     */
    /**
     * food - instance of the Item Food to be held within inventory.
     */
    /**
     * fuelCells - instance of the Item FuelCell to be held within inventory.
     */
    /**
     * money - instance of the Item money that holds the players money in the inventory.
     */
    private final Item money, fuelCells, food, hullParts, fCapacitors, engines;

    /**
     * timeBulletBills - instance of the Item TimeBulletBill that acts as ammunition.
     */
    /**
     * timeSuits - instance of the Item TimeSuit that acts as clothing in the inventory.
     */
    private final Item timeSuits, timeBulletBills;

    /**
     * INV_CAPACITY - the maximum amount of weight a player can hold.
     * (value is 3500)
     */
    private static final int INV_CAPACITY = 3500;

    /**
     * INV_MIN - the minimum amount of weight a player could hold.
     * (value is 0)
     */
    private static final int INV_MIN = 0;

    /**
     * invWeight - the current weight held in the inventory.
     */
    private int invWeight;
    
    /**
     * A List of the items in the inventory
     */
    private List<Item> itemList;
    
    /**
     * Constructor for Inventory.
     * Creates instances of all the items to be held in the inventory.
     * Sets initial weight to zero.
     */
    public Inventory(){
        itemList = new ArrayList<Item>();
        invWeight = 0;
        
        money = new Money();
        fuelCells = new FuelCell();
        food = new Food();
        hullParts = new HullPart();
        fCapacitors = new FluxCapacitor();
        engines = new Engine();
        timeSuits = new TimeSuit();
        timeBulletBills = new TimeBulletBill();
        itemList.add(money);
        itemList.add(fuelCells);
        itemList.add(food);
        itemList.add(hullParts);
        itemList.add(fCapacitors);
        itemList.add(engines);
        itemList.add(timeSuits);
        itemList.add(timeBulletBills);


    }

    /**
     * adds an item to the inventory without dealing with things like "cost" and "money"
     * things like weight and capacity will still affect it
     * @param amount how many items to be received 
     * @param item what kind of item to be received
     */
    public void addItem(int amount, Item item){
        final boolean addConfirm = item.canAddCurrentAmount(amount);
        final int weightCheck = item.getWeight() * amount;
        
        if(addConfirm && (invWeight + weightCheck) <= INV_CAPACITY 
                && (invWeight + weightCheck) >= INV_MIN){
            invWeight += weightCheck;
            item.addCurrentAmount(amount);
        }
        
        else{
            return;
        }
    }
    
    /**
     * DOES NOT ADD AN ITEM TO THE INVENTORY, but it does test if it's possible
     * @param amount the amount of an item that you are trying to add to the inventory
     * @param item the item you are trying to add to the inventory
     * @return true if it's possible to add to the inventory, false if it isn't.
     */
    public boolean canAddItem(int amount, Item item){
        final boolean addConfirm = item.canAddCurrentAmount(amount);
        final int weightCheck = item.getWeight() * amount;
        
        return addConfirm && invWeight + weightCheck <= INV_CAPACITY 
                    && invWeight + weightCheck >= INV_MIN;
    }

    /**
     * remove an item from the inventory without dealing with money
     * still refactors weight when removed
     * this is basically a call to add item, but with a more intuitive name
     * @param amount the amount of items to remove from the inventory  
     * @param item the type of item to remove
     */
    public void removeItem(int amount, Item item){
        if(amount < 0){
            return;
        }
        else{
            addItem((amount * -1), item);
        }
    }
    
    /**
     * DOES NOT REMOVE ANYTHING FROM THE INVENTORY but does test if it's possible
     * @param amount the amount of the item you want to remove
     * @param item the item you want to remove
     * @return true if it's possible, false if it's not
     */
    public boolean canRemoveItem(int amount, Item item){
        if(amount < 0){
            return false;
        }
        else{
            return canAddItem((amount * -1), item);
        }
    }

    /**
     * returns the real weight of the inventory
    
     * @return the inventory's current weight */
    public int getInvWeight() {
        return invWeight;
    }
    
    /**
     * sets the inventory weight, if the weight would not work return false
     * @param invWeight the weight to set the inventory to
    
     */
    public void setInvWeight(int invWeight) {
            this.invWeight = invWeight;
        
    }

    /**
     * returns the instance of Money the person has
    
     * @return the inventory's money */
    public Item getMoney() {
        return money;
    }

    /**
     * returns the fuel cells of the inventory.
    
     * @return the inventory's fuel cells */
    public Item getFuelCells() {
        return fuelCells;
    }

    /**
     * returns the inventory's food
    
     * @return the inventory's food */
    public Item getFood() {
        return food;
    }

    /**
     * returns the inventory's hull parts.
    
     * @return the inventory's hull parts */
    public Item getHullParts() {
        return hullParts;
    }

    /**
     * returns the flux capacitors of the inventory.
    
     * @return the inventory's flux capacitors */
    public Item getfCapacitors() {
        return fCapacitors;
    }

    /**
     * returns the engines of the inventory.
    
     * @return the inventory's engine */
    public Item getEngines() {
        return engines;
    }

    /**
     * returns the clothing of the inventory.
    
     * @return the Time Suits of the inventory */
    public Item getTimeSuits(){
        return timeSuits;
    }

    /**
     * returns the time bullet bills to the inventory.
    
     * @return the inventory's time bullet bills */
    public Item getTimeBulletBills(){
        return timeBulletBills;
    }

    /**
     * returns the inventory's maximum capacity
    
     * @return the inventory's maximum capacity */
    public int getCapacity() {
        return INV_CAPACITY;
    }
    
    /**
     * Gives the string representation of the inventory.
     * @return the string representation of the inventory
     */
    public String toString(){
        
        return  "Weight: " + invWeight + "\n " +
                money.toString() + ": " + money.getCurrentAmount() + "\n " +
                fuelCells.toString() + ": " + fuelCells.getCurrentAmount() + "\n " +
                food.toString() + ": " + food.getCurrentAmount() + "\n " +
                hullParts.toString() + ": " + hullParts.getCurrentAmount() + "\n " + 
                fCapacitors.toString() + ": " + fCapacitors.getCurrentAmount() + "\n " + 
                engines.toString() + ": " + engines.getCurrentAmount() + "\n " + 
                timeSuits.toString() + ": " + timeSuits.getCurrentAmount() + "\n " + 
                timeBulletBills.toString() + ": " + timeBulletBills.getCurrentAmount();
        
    }
    
    /**
     * gives you an instance of a random item in the inventory
     * @return
     */
    public Item getRandomItem(){
        Random rand = new Random();
        return itemList.get(rand.nextInt(itemList.size()));
    }

}




